import 'dart:math';

import 'package:flutter/material.dart';

extension ListEx<E> on List<E> {
  List<E> takeSublist({
    required List<int> indexs,
  }) {
    List<E> items = [];
    for (var i = 0; i < length; i++) {
      if (indexs.contains(i)) {
        var e = this[i];
        items.add(e);
      }
    }
    return items;
  }

  E? filterFirst(
    bool Function(E) test,
  ) {
    var l = where((test));

    if (l.isNotEmpty) {
      return l.first;
    }

    return null;
  }

  void addForRepel(E e) {
    assert(() {
      if (e is! ObjectEx) {
        throw FlutterError('repel函数，元素必须继承ObjectEx,以便使用key属性，进行相斥');
      }
      return true;
    }());
    if (isEmpty) {
      add(e);
      return;
    }
    if (!has(e)) {
      add(e);
    }
  }

  void addAllForRepel(List<E> data) {
    assert(() {
      if (data.whereType<ObjectEx>().isEmpty) {
        throw FlutterError('repel函数，元素必须继承ObjectEx,以便使用key属性，进行相斥');
      }
      return true;
    }());
    if (isEmpty) {
      addAll(data);
      return;
    }
    for (var element in data) {
      if (!has(element)) {
        add(element);
      }
    }
  }

  void insertForRepel(int index, E e) {
    assert(() {
      if (e is! ObjectEx) {
        throw FlutterError('repel函数，元素必须继承ObjectEx,以便使用key属性，进行相斥');
      }
      return true;
    }());
    if (isEmpty) {
      add(e);
      return;
    }
    if (!has(e)) {
      insert(0, e);
    }
  }

  void insertAllForRepel(int index, List<E> data) {
    assert(() {
      if (data.whereType<ObjectEx>().isEmpty) {
        throw FlutterError('repel函数，元素必须继承ObjectEx,以便使用key属性，进行相斥');
      }
      return true;
    }());
    if (isEmpty) {
      addAll(data);
      return;
    }
    List<E> nl = [];

    for (var element in data) {
      if (!has(element)) {
        nl.add(element);
      }
    }

    insertAll(0, nl);
  }

  bool has(E e) {
    assert(() {
      if (whereType<ObjectEx>().isEmpty) {
        throw FlutterError('repel函数，元素必须继承ObjectEx,以便使用key属性，进行相斥');
      }
      return true;
    }());
    return where((element) {
      return (element as ObjectEx).idKey == (e as ObjectEx).idKey;
    }).isNotEmpty;
  }

  bool have(bool Function(E) test) {
    var isHave = false;
    for (var e in this) {
      isHave = test(e);
      if (isHave) {
        break;
      }
    }
    return isHave;
  }

  bool havenot(bool Function(E) test) {
    var isHave = true;
    for (var e in this) {
      isHave = test(e);
      if (!isHave) {
        break;
      }
    }
    return isHave;
  }

  void move(
    E e, {
    required int to,
  }) {
    int index = indexOf(e);
    if (index < 0) return;
    removeAt(index);
    insert(min(max(0, to), length), e);
  }

  void addOr(E e) {
    if (!contains(e)) {
      add(e);
    }
  }

  void insertOr(int index, E e) {
    if (!contains(e)) {
      insert(index, e);
    }
  }

  void exchange(int start, int end) {
    if (start < 0 || start > length || end < 0 || end > length) {
      return;
    }
    var e1 = this[start];
    var e2 = this[end];
    move(e1, to: end);
    move(e2, to: start);
  }
}

class ObjectEx extends Object {
  String idKey = '';
}
